package com.zdpx.wordgen.controller;


import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zdpx.wordgen.domain.*;
import com.zdpx.wordgen.service.WordService;
import com.zdpx.wordgen.utils.HttpServletUtil;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.TransformException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

@RestController
public class WordController {
    @Autowired
    private WordService wordService;
    @RequestMapping(value = "/getWordFromData",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public void handleFileUpload(@RequestParam("file") Optional<MultipartFile> file,  @RequestParam("contentData") Optional<String> data, int isPdf, String fileName) throws Exception {
        String templatePath = "template.docx";     // 替换成输出路径
        HttpServletResponse response = HttpServletUtil.getResponse();
        ServletOutputStream outputStream = response.getOutputStream();
        InputStream inputStream;
        docDataFmt docData;
        ObjectMapper mapper=new ObjectMapper();
        if(!data.isPresent())
            docData=mapper.readValue("{}",docDataFmt.class);
        else
            docData=mapper.readValue(data.get(),docDataFmt.class);
        if(!file.isPresent())
             inputStream = new FileInputStream(templatePath);
        else
            inputStream = new ByteArrayInputStream(file.get().getBytes());
        try {
            if (hasDocData(docData)) {
                XWPFDocument templateDoc = new XWPFDocument(inputStream);
                XWPFDocument wordDoc = wordService.generateWord(templateDoc, docData);
                if (isPdf == 1) {
                    //pdf页面直接显示
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    wordDoc.write(baos);
                    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                    //转换生成输入流生成pdf
                    response.setHeader("Content-Disposition", "inline;filename=" + fileName + ".pdf");
                    response.setContentType("application/pdf; charset=UTF-8");
                    Document doc= new Document(bais);
                    doc.save(outputStream, SaveFormat.PDF);
                    outputStream.flush();
                }
                else
                    {
                        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".docx");
                        response.setHeader("Content-Type", "application/octet-stream");
                        wordDoc.write(outputStream);
                        outputStream.flush();
                    }
                }
               else if (isPdf==1) {
                    response.setHeader("Content-Disposition", "inline;filename=" + fileName + ".pdf");
                    response.setContentType("application/pdf; charset=UTF-8");
                    Document doc = new Document(inputStream);
                    doc.save(outputStream, SaveFormat.PDF);
                    outputStream.flush();
                }
            } catch(Exception e){
                System.out.println("文件处理失败: " + e.getMessage());
            } finally{
                if (outputStream != null) {
                    try {
                        inputStream.close();
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    }

    @RequestMapping("/putFile")
    public String uploadFile(@RequestParam("file") Optional<MultipartFile> file,@RequestParam("data") Optional<String> data) throws IOException {
        ObjectMapper mapper=new ObjectMapper();
        ClientInfo subject=new ClientInfo();
        try {
            subject=mapper.readValue(data.get(),ClientInfo.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return "Error:ClientInfo Deserialize";
        }
        if(!file.isPresent())
            return "Error:File is empty";
        int clientSize=clientMap.size();
        int forwardSize=0;
        for (String key:clientMap.keySet()) {
             if(isNeedPostFile(subject,clientMap.get(key))) {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.MULTIPART_FORM_DATA);
                MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
                Resource resource = file.get().getResource();
                formData.add("file", resource);
                RestTemplate restTemplate = new RestTemplate();
                HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(formData, headers);
                String retRes = restTemplate.postForObject(key, entity, String.class);
                forwardSize++;
                System.out.println("Forword:"+key+",\nResponse: " + retRes);
            }
        }
        return String.valueOf(forwardSize)+":"+String.valueOf(forwardSize);
    }

    @RequestMapping("/regFileReceiveUrl")
    public String regiesterFileApi(int port,@RequestBody ClientInfo data) {
        Optional<ClientInfo> dataOpt=Optional.ofNullable(data);
        if(!dataOpt.isPresent())
            return "Error:ClientInfo";
        if(port<80)
            return "Error:Port";
        HttpServletRequest request = HttpServletUtil.getRequest();
        String remoteIp=request.getRemoteAddr();
        String url="http://"+remoteIp+":"+String.valueOf(port)+"/uploadFile";
        clientMap.put(url,data);
        System.out.println(url+",registered");
        return "Success:Register";
    }

    @RequestMapping("/clearClients")
    public String clearClientMaps() throws IOException, FactoryException, TransformException {
        Iterator<Map.Entry<String,ClientInfo> > it=clientMap.entrySet().iterator();
        while(it.hasNext())
        {
            Map.Entry<String,ClientInfo> entry=it.next();
            if(!entry.getKey().equals(""))
                it.remove();
        }
        return "success:ClientMap Cleared!";
    }



    @RequestMapping("/getClients")
    public List<String> getClientMaps()
    {
        HeatData heatData=new HeatData();
        heatData.setCrs("4326");
        heatData.setHasValue(false);
        heatData.setHeight(500);
        heatData.setWidth(500);
        ArrayList<Postion> posData=new ArrayList<>();
        Postion pos=new Postion(121.10195, 24.0200,0.0);
        Postion pos2=new Postion(121.10195, 24.0200,0.0);
        Postion pos3=new Postion(121.10195, 24.0200,0.0);
        posData.add(pos);
        posData.add(pos2);
        posData.add(pos3);
        heatData.setPosValData(posData);
        posRange range=new posRange(121.0134, 121.5234, 24.0031, 24.5131);
        heatData.setRange(range);

        List<String> clientList=new LinkedList<>();
        for(String key:clientMap.keySet())
        {
            clientList.add(key);
        }
        return clientList;
    }

    @PostMapping("/getHeatmap")
    public String getDataTiff(@RequestBody HeatData heatData)
    {
        String fileId="";
        List<Postion> posValData = heatData.getPosValData();
        TiffGen tfg=new TiffGen();
        try {
           fileId= tfg.buildGeo(heatData);
        } catch (IOException | FactoryException e) {
            e.printStackTrace();
        }
        return fileId;
    }

    @RequestMapping("/getTiff")
    public String getTiffImg(@RequestParam("img") String fileId) throws IOException, FactoryException, TransformException {
        TiffGen tfg=new TiffGen();
        tfg.readTiff(fileId);
        return "success:ClientMap Cleared!";
    }

    private boolean isNeedPostFile(ClientInfo server,ClientInfo client)
    {
        if(server.getGrade()==client.getGrade()&&(server.getSeat()==client.getSeat()))
            return true;
        else
            return false;
    }
    private boolean hasDocData(docDataFmt data)
    {
        return (data.getTable().size()>0||data.getContent().size()>0);
    }
    private static Map<String,ClientInfo> clientMap=new HashMap<>();
}